<template>
  <v-map
      class="map"
      ref="map"
      :view="view"
      :controls="controls"
      :interactions="interactions"
      @click="onClick"
      @load="onLoad"
  >
    <v-tile :tile-type="tileType" :xyz="xyz"></v-tile>
<!--    <v-echarts :options="echarts.options"></v-echarts>-->
    <ol-echarts ref="ol-echarts" :options="echarts.options" :lazyConfig="lazyConfig" @click="onEchartsClick" @load="onOlEchartsLoad"></ol-echarts>
  </v-map>

</template>

<script>
import anaList from '@/assets/json/anaList.json'
import startIcon from '@/assets/map/start.png'
import endIcon from '@/assets/map/end.png'
import trackList from '@/assets/json/trackList.json'
import { debounce } from 'lodash'

export default {
  name: 'activityTrack',
  data () {
    return {
      map: null,
      olEcharts: null,
      lazyConfig:{
        isLazy: true,
        wait: 200
      },
      view: {
        center: [103.22836816745777, 25.23964540709535], // 中心点
        projection: 'EPSG:4326',
        zoom: 12,
        minZoom: 1,
        maxZoom: 20,
        extent: [73.55, 18.16, 135.08, 53.55], // 设置视图范围为中国边界范围
        constrainResolution: true // 设置为true，确保地图不会显示超出中国范围的部分
      },
      controls: {},
      interactions: {
        DragRotateAndZoom: true,
        doubleClickZoom: false,
        dragPan: true,
        mouseWheelZoom: true
      },
      // 图层类型
      tileType: 'XYZ',
      xyz: {
        url: 'http://172.20.5.141:8088/styles/osm-bright/{z}/{x}/{y}.png'
      },
      echarts: {
        options: {},
        points: [],
        lines: []
      }
    }
  },
  methods: {
    onMapViewChange: debounce(function () {
      // 获取地图的可视范围
      const viewExtent = this.map.getView().calculateExtent(this.map.getSize())
      const points = this.echarts.points.filter(x => {
        const coordinate = x.value
        // 判断屏幕坐标是否在可视范围内
        const isInsideView = this.$refs.map.containsCoordinate(viewExtent, coordinate)
        return isInsideView
      })
      const lines = this.echarts.lines.filter(x => {
        const lineCoordinates = x.coords
        // 判断线是否与地图可视范围的边界框相交
        const lineExtent = this.$refs.map.boundingExtent(lineCoordinates)
        const isIntersect = this.$refs.map.intersects(viewExtent, lineExtent)
        return isIntersect
      })
      this.echarts.options = this.setEchartsOptions(lines, points)
      this.$nextTick(() => {
        this.olEcharts.resetOption(this.echarts.options)
      })
    },200),
    onClick (evt, map) {
      console.log(evt, map)
    },
    onEchartsClick (param) {
      console.log(param)
    },
    // 地图对象生成完成事件
    onLoad (map) {
      this.map = map
    },
    onOlEchartsLoad (charts) {
      this.olEcharts = charts
      this.handlePointsData()
    },
    handlePointsData () {
      const allData = trackList.map((x, i) => ({
        id: i + 1,
        uuid: `${x.lng},${x.lat}`,
        uuid_: `${x.alac}${x.aci}`,
        ...x,
      }))
      const filterData = allData.filter(x => x.lng && x.lat)
      const baseData = filterData.map(y => y.uuid)
      const pointData = Array.from(new Set(baseData)) // 坐标点去重
      const points = pointData.map(x => {
        const coordinates = x.split(',')
        const points = filterData.filter(y => y.uuid === x).sort((a, b) => b.id - a.id)
        const text = points.length > 1 ? `${points[0].id}...` : points[0].id || ''
        return {
          lon: Number(coordinates[0]),
          lat: Number(coordinates[1]),
          text
        }
      })
      const poiToPoiData = []
      // 将坐标数据处理为点对点轨迹数据并去重
      baseData.reduce((prev, cur) => {
        const lineStr = `${prev}-${cur}` // '103.30543114192292,25.13612093139482-102.71348785044621,25.052667381200198' 点对点数据 即一条线
        // 如果坐标存在 且poiToPoiData里没有这条线，则放入poiToPoiData（起始、终止坐标相同的线去重）
        if (prev && prev !== cur && !poiToPoiData.includes(lineStr)) poiToPoiData.push(lineStr)
        return cur
      }, '')
      this.echarts.points = points.map((x, i) => {
        const res = { value: [x.lon, x.lat] }
        switch (i) {
          case 0:
            res.type = 'start'
            res.image = startIcon
            break
          case points.length - 1:
            res.type = 'end'
            res.image = endIcon
            break
          default:
            res.type = 'normal'
            res.text = x.text
            break
        }
        return { ...res }
      })
      this.echarts.lines = this.convertData(poiToPoiData)
      this.echarts.options = this.setEchartsOptions(this.echarts.lines, this.echarts.points)
      this.$nextTick(() => {
        this.olEcharts.resetOption(this.echarts.options)
      })
    },
    setEchartsOptions (lines, points) {
      const lineSeries = this.initLineSeries(lines)
      const pointSeries = this.initPointSeries(points)
      const series = lineSeries.concat(pointSeries)
      return {
        series
      }
    },
    initLineSeries (data) {
      if(!data || data.length === 0)return []
      const series = [
        {
          // 小图标的特效
          name:'lines',
          type: 'lines',
          zlevel: 1,
          effect: {
            show: false,
            period: 10, // 时间s
            trailLength: 0,
            // symbol还可以指定图片路径 格式如:'image://图片地址'
            symbol: 'path://M250 150 L150 350 L350 350 Z',
            symbolSize: 10
          },
          lineStyle: {
            normal: {
              color: '#FF0000',
              width: 1,
              // type:'dashed',
              // dashOffset:1,
              opacity: 0.4,
              curveness: 0.2
            }
          },
          data
        }
      ]
      if(data.length < 500){
        series.push({
          // 小图标屁股冒烟的特效
          name:'lines',
          type: 'lines',
          zlevel: 1,
          effect: {
            show: false,
            // 冒烟跑的速度(值越小越快)
            period: 10,
            // 屁股冒烟的长度
            trailLength: 0.5,
            // 冒什么颜色的烟
            color: 'red',
            // 冒好粗的烟
            symbolSize: 3
          },
          lineStyle: {
            normal: {
              color: '#FF0000',
              width: 0,
              curveness: 0.2
            }
          },
          data
        })
      }
      return series
    },
    initPointSeries (data) {
      if(!data || data.length === 0)return []
      let series = []
      const labelData = data.filter(x => x.type === 'normal').map(item => ({
        name: item.text,
        value: item.value
      }))
      const imageData = data.filter(item => item.type === 'start' || item.type === 'end').map(item => ({
        name: item.text,
        value: item.value,
        symbol: `image://${item.image}`
      }))
      const labelSeries = {
        name:'label-scatter',
        type: 'scatter',
        zlevel: 2,
        data: labelData,
        label: {
          show: true,
          formatter: '{b}',
          fontSize: 14,
          color: '#ffffff',
          position: 'inside',
          align: 'center',
          verticalAlign: 'middle',
          width: 45,
          height: 28,
          backgroundColor: '#ff512b',
          borderWidth: 2,
          borderColor: '#ffffff',
          borderRadius: 5
        },
        itemStyle: {
          color: 'transparent',
          opacity: 1
        }
      }
      const imageSeries = {
        name:'image-scatter',
        type: 'scatter',
        zlevel: 2,
        data: imageData,
        symbolSize: [60, 69],
        symbolOffset: [0, -24],
        symbolBoundingData: 1,
        z: 3,
        itemStyle: {
          opacity: 1
        }
      }
      if(labelData && labelData.length)series.push(labelSeries)
      if(imageData && imageData.length)series.push(imageSeries)
      return series
    },
    convertData (data) {
      return data.map(x => {
        const arr = x.split('-')
        const fromCoord = this.formatStrToCoord(arr[0])
        const toCoord = this.formatStrToCoord(arr[1])
        return { coords: [fromCoord, toCoord] }
      })
    },
    formatStrToCoord (str) {
      return str.split(',').map(Number)
    }
  },
  mounted () {

  }
}
</script>

<style scoped>

</style>
